import logging
from rest_framework import status
from rest_framework.generics import GenericAPIView
from rest_framework.response import Response
from rest_framework.views import APIView

from cart.utils import merge_cookie_cart_to_redis
from oauth.exceptions import QQAPIError, WBAPIError
from oauth.models import OauthQQUser, OAuthSinaUser
from oauth.serializers import QQAuthUserserializer, WBAuthUserserializer
from oauth.utils import OAuthQQ, OAuthWB

logger = logging.getLogger('django')
# 根据扫码登录成功的得到的code,服务器根据code获取QQ服务器的access_token-->openid
# GET /oauth/qq/user/?code=<code>
class QQAuthUserView(GenericAPIView):
    serializer_class = QQAuthUserserializer
    # 保存绑定数据
    def post(self,request):

        # 1 获取参数并校验access_token,mobile,password,sms_code
        serialzer = self.get_serializer(data=request.data)
        serialzer.is_valid(raise_exception=True)
        # 2 对用户信息保存
        serialzer.save()
        # 3 返回应答
        response = Response(serialzer.data, status=status.HTTP_201_CREATED)
        user = self.user
        merge_cookie_cart_to_redis(request, user, response)
        return response


    def get(self,request):
        # 1 获取查询字符串的参数code
        code = request.query_params.get('code')
        if code is None:
            return Response({'message':'缺少参数'},status=status.HTTP_400_BAD_REQUEST)
        try:
        # 2 获取openid
            # 2.1 获取acces_token
            oauth = OAuthQQ()
            access_token = oauth.get_access_token(code)
            # 2.2 获取openid
            openid = oauth.get_openid(access_token)
            logger.info('%s号用户的openid是%s' % (request.user.id,openid))
        except QQAPIError:
            return Response({'message': 'QQ登录异常'}, status=status.HTTP_503_SERVICE_UNAVAILABLE)

        # 3 根据openid获取用户id
        try:
            qq_user = OauthQQUser.objects.get(openid=openid)
        except OauthQQUser.DoesNotExist:
            # 如果没有绑定,将openid进行加密返回
            secret_openid = oauth.generate_save_user_token(openid)
            return Response({'access_token':secret_openid})
        else:
            # 如果绑定了,生成JWTtokne进行返回
            user =qq_user.user

            # 手动签发JWT token的值
            from rest_framework_jwt.settings import api_settings
            # 指定生成payload的方法,pyload可以自定义,但是这个里值返回token值
            jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
            jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
            # 生成payload
            payload = jwt_payload_handler(user)
            token = jwt_encode_handler(payload)

            res_data = {
                'user_id':user.id,
                'username':user.username,
                'token':token
            }
            response = Response(res_data)

            # 调用购物车合并函数进行合并
            merge_cookie_cart_to_redis(request, user, response)
            return response


# 获取QQ的login_url给客户端返回,让客户端直接访问
# GET /oauth/qq/authorization/?next=<登录之后访问页面地址>
class QQAuthUrlView(APIView):
    '''
    1. 获取next
    2. 组织QQ登录网址和参数
    3. 返回QQ登录网址
    '''
    def get(self,requset):
        next = requset.query_params.get('next','/')

        oauth = OAuthQQ(state=next)
        qq_login_url = oauth.get_login_url()

        return Response({'login_url':qq_login_url})



# 获取weibo的login_url给客户端返回,让客户端直接访问
# GET /oauth/weibo/authorization/?next=<登录之后访问页面地址>
class WeiboAuthUrlView(APIView):
    '''
    1. 获取next
    2. 组织weibo登录网址和参数
    https://api.weibo.com/oauth2/authorize?client_id=123050457758183&redirect_uri=http://www.meiduo.site:8080/sina_callback.html
    3. 返回weibo登录网址
    '''
    def get(self,requset):
        next = requset.query_params.get('next','/')

        oauth = OAuthWB(state=next)
        weibo_login_url = oauth.get_login_url()

        return Response({'login_url':weibo_login_url})

# 根据扫码登录成功的得到的code,服务器根据code获取weibo服务器的access_token
# GET /oauth/sina/user/?code=<code>
class WBAuthUserView(GenericAPIView):
    serializer_class = WBAuthUserserializer
    # 保存绑定数据
    def post(self,request):

        # 1 获取参数并校验access_token,mobile,password,sms_code
        serialzer = self.get_serializer(data=request.data)
        serialzer.is_valid(raise_exception=True)
        # 2 对用户信息保存
        serialzer.save()
        # 3 返回应答
        response = Response(serialzer.data, status=status.HTTP_201_CREATED)
        user = self.user
        merge_cookie_cart_to_redis(request, user, response)
        return response

    # 获取token判断是否绑定
    def get(self,request):
        # 1 获取查询字符串的参数code
        code = request.query_params.get('code')
        if code is None:
            return Response({'message':'缺少参数'},status=status.HTTP_400_BAD_REQUEST)
        try:
            # 2 获取acces_token
            oauth = OAuthWB()
            access_token = oauth.get_access_token(code)
            logger.info('%s号用户的access_token是%s' % (request.user.id,access_token))
        except WBAPIError:
            return Response({'message': '微薄登录异常'}, status=status.HTTP_503_SERVICE_UNAVAILABLE)

        # 3 根据access_token获取用户id
        try:
            weibo_user = OAuthSinaUser.objects.get(access_token=access_token)
        except OAuthSinaUser.DoesNotExist:
            # 如果没有绑定,将token进行加密返回
            secret_openid = oauth.generate_save_user_token(access_token)
            return Response({'access_token':secret_openid})
        else:
            # 如果绑定了,生成JWTtokne进行返回
            user =weibo_user.user

            # 手动签发JWT token的值
            from rest_framework_jwt.settings import api_settings
            # 指定生成payload的方法,pyload可以自定义,但是这个里值返回token值
            jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
            jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
            # 生成payload
            payload = jwt_payload_handler(user)
            token = jwt_encode_handler(payload)

            res_data = {
                'user_id':user.id,
                'username':user.username,
                'token':token
            }
            response = Response(res_data)

            # 调用购物车合并函数进行合并
            merge_cookie_cart_to_redis(request, user, response)
            return response